const Dispatcher = require('./dispatcher');

const utils = {
    asObject(array, deep = false) {
        if (Array.isArray(array) || typeof array === 'object' && deep) {
            let object = { };
            for (let [ key, value ] of Object.entries(array)) {
                if (value instanceof Dispatcher) object[key] = value.data;
                else object[key] = deep ? utils.asObject(value, deep) : value;
            }
            return object;
        } else {
            return array;
        }
    },
    asArray(object, deep = false) {
        if (typeof object === 'object') {
            let keys = Object.keys(object);
            if (keys.every(key => key !== '__ob__' && !isNaN(key) && parseInt(key) === parseFloat(key))) {
                let maxIndex = keys.filter(key => key !== '__ob__').reduce((s, v) => Math.max(~~s, ~~v), -1);
                let length = maxIndex + 1;
                let array = object['-1'] || [];
                if (array.length < length) array.splice(array.length, 0, ...new Array(length - array.length).fill(undefined));
                if (array.length > length) array.splice(length, array.length - length);
                for (let [ key, value ] of Object.entries(object)) {
                    if (key !== '-1' && key !== '__ob__') {
                        array[~~key] = deep && typeof value === 'object' ? utils.asArray(value, deep) : value;
                    }
                }
                object['-1'] = array;
                return array;
            } else if (deep) {
                let result = object['-1'] || { };
                for (let [ key, value ] of Object.entries(object)) {
                    if (key !== '-1') {
                        result[key] = typeof value === 'object' ? utils.asArray(value, deep) : value;
                    }
                }
                object['-1'] = result;
                return result;
            }
        }
        return object;
    },
    randomIndex(arrayOrString) {
        return Math.floor(arrayOrString.length * Math.random());
    },
    random(arrayOrString) {
        if (Array.isArray(arrayOrString)) {
            return arrayOrString[this.randomIndex(arrayOrString)];
        } else {
            return arrayOrString.charAt(this.randomIndex(arrayOrString));
        }
    },
    shuffle(arrayOrString) {
        if (Array.isArray(arrayOrString)) {
            let length = arrayOrString.length;
            let temp, index;
            for (let i = 0; i < length; i++) {
                index = Math.floor(Math.random() * length);
                if (i !== index) {
                    temp = arrayOrString[index];
                    arrayOrString[index] = arrayOrString[i];
                    arrayOrString[i] = temp;
                }
            }
            return arrayOrString;
        } else {
            return this.shuffle(arrayOrString.split('')).join('');
        }
    }
};

module.exports = utils;